package com.spica.spicaschool.network.repository

import androidx.annotation.WorkerThread
import com.skydoves.sandwich.map
import com.skydoves.sandwich.onError
import com.skydoves.sandwich.onException
import com.skydoves.sandwich.suspendOnSuccess
import com.skydoves.whatif.whatIfNotNull
import com.spica.spicaschool.network.ErrorResponseMapper
import com.spica.spicaschool.network.SpicaClient
import com.spica.spicaschool.persistence.dao.UserDao
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onCompletion
import timber.log.Timber
import javax.inject.Inject


/**
 * 用户信息的Repository
 */
class UserRepository @Inject constructor(
    private val userDao: UserDao,
    private val spicaClient: SpicaClient
) : Repository {

    /**
     * 获取用户信息
     */
    @WorkerThread
    fun fetchInfo(
        token: String,
        onComplete: () -> Unit,
        onError: (String?) -> Unit
    ) = flow {
        //获取数据库中用户信息
        val user = userDao.queryUser()
        //如果查询数据库有数据直接返回用于响应页面更新
        if (user != null) emit(user)
        //请求数据
        val response = spicaClient.fetchUserInfo(token)
        response.suspendOnSuccess {
            data.whatIfNotNull { response ->
                //请求数据成功，接入缓存
                userDao.insertUser(response.data[0])
                //通知页面更新
                emit(response.data[0])
            }
        }.onError {
            //服务器错误的回调
            map(ErrorResponseMapper()) {
                onError("[Code: $code]: $msg")
            }
        }.onException {
            //客户端错误
            onError(message)
        }
    }.onCompletion {
        //触发流程结束的回调
        onComplete()
    }//指定运行线程
        .flowOn(Dispatchers.IO)


    /**
     * 获取用户的身体状况信息
     */
    @WorkerThread
    fun fetchUserBodyInfo(token: String) = flow {
        val response = spicaClient.fetchUserBodyInfo(token)
        response.suspendOnSuccess {
            data.whatIfNotNull {
                emit(it.data[0])
            }
        }
    }.flowOn(Dispatchers.IO)


    @WorkerThread
    fun updateUserInfo(
        token: String,
        head: String? = null,
        nickname: String? = null,
        selfdes: String? = null,
        gender: Int? = null,
        birthday: String? = null,
        height: Int? = null,
        weight: Int? = null,
        vialCap: Int? = null,
        onComplete: () -> Unit,
        onError: (String?) -> Unit
    ) = flow {
        Timber.e("更新用户信息")
        val response = spicaClient.updateUserInfo(
            token,
            head,
            nickname,
            selfdes,
            gender,
            birthday,
            height,
            weight,
            vialCap
        )
        response.suspendOnSuccess {
            Timber.e("更新用户信息成功${data?.msg}")
            emit(data?.msg)
        }.onError {
            //服务器错误的回调
            map(ErrorResponseMapper()) {
                Timber.e("更新用户信息失败$msg")
                onError("[Code: $code]: $msg")
            }
        }.onException {
            Timber.e("更新用户信息失败：$message")
            //客户端错误
            onError(message)
        }
    }.onCompletion {
        //触发流程结束的回调
        onComplete()
    }.flowOn(Dispatchers.IO)

}